#include <ClanLib/core.h>
#include <ClanLib/application.h>
#include <ClanLib/display.h>
#include <ClanLib/gl.h>
#include <ClanLib\sound.h>
#include "World.h"
#include "WorldSound.h"
#include "ActorMario.h"
#include "CollisionDetection.h"
#include "ActorDonkeyKong.h"
#include "ActorPrincess.h"
#include "ActorOilbarrel.h"
//#define SHOW_OUTLINES

enum GameState{begin, play, win, loos, gameover};

class ConsoleProgram
{
public:
	static int main(const std::vector<CL_String> &args)
	{
		int lifes = 3;
		CollisionDetection* collision;
		ActorMario* mario;
		ActorDonkeyKong* donkeykong;
		ActorPrincess* princess;
		ActorOilbarrel* oilbarrel;
		CL_SetupCore setup_core;
		CL_SetupDisplay setup_display;
		CL_SetupGL setup_gl;
		CL_SetupSound setup_sound;
		CL_SoundOutput output(44100);
		
		GameState gamestate;
		unsigned int last_time = CL_System::get_time();
		unsigned int current_time = 0;
		int time_difference = 0;
		float time_delta_ms = 0;
		const int main_loop_rate = 7;	// 10 ms (100 hz)
		int time_to_sleep_for = 0;

		gamestate = play;
		CL_DisplayWindow window("Donkey Kong", 560, 680);
		CL_GraphicContext gc = window.get_gc();
		CL_InputContext ic = window.get_ic();

		princess = new ActorPrincess(gc);
		donkeykong = new ActorDonkeyKong(gc);
		mario = new ActorMario(gc);
		mario->setPosition(130, 605);
		collision = CollisionDetection::giveme();
		oilbarrel = new ActorOilbarrel(gc);
		//

		World* w=new World(gc,"./resource/level1.png");
		World* g=new World(gc,"./resource/gameover.png"); 
		WorldSound* wsound=new WorldSound();
		wsound->backgroundmusic();

		while (ic.get_keyboard().get_keycode(CL_KEY_ESCAPE) == false)
		{
			current_time = CL_System::get_time();
			time_difference = current_time - last_time;
			if (time_difference > 1000)
				time_difference = 1000;		// Limit the time difference, if the application was paused (eg, moving the window on WIN32)
			time_delta_ms = static_cast<float> (time_difference);
			last_time = current_time;

			gc.clear(CL_Colorf::black);
			//	CL_Gradient color(CL_Colorf::mediumspringgreen, CL_Colorf::honeydew);
			//	CL_Draw::gradient_fill(gc, 0.0f, 0.0f, 100.0f, 100.0f, color);
			w->getGrafikMap()->draw(gc, 0, 0);
#ifdef SHOW_OUTLINES
			mario->drawLadders(gc);
			mario->drawOutline(gc);
#endif
			switch(gamestate){
			case begin:
				//TODO intro animieren
				break;
			case play:
				if(collision->win())
				{
					gamestate = win;
					wsound->levelcomplete();
				}
				if(donkeykong->hasplayerlost() || oilbarrel->hasplayerlost())
				{
					gamestate = loos;
					wsound->deathofplayer();
					lifes--;
				}
				collision->setmario(mario->getPosition());
				if(ic.get_keyboard().get_keycode(CL_KEY_RIGHT)&&!ic.get_keyboard().get_keycode(CL_KEY_LEFT)){
					if(ic.get_keyboard().get_keycode(CL_KEY_SPACE) || mario->IsJumping())
					{
						mario->Jump(right);
					}
					else
					{
						mario->Run(false);
					}
				}else if(ic.get_keyboard().get_keycode(CL_KEY_LEFT)&&!ic.get_keyboard().get_keycode(CL_KEY_RIGHT)){
					if(ic.get_keyboard().get_keycode(CL_KEY_SPACE) || mario->IsJumping())
					{
						mario->Jump(left);
					}
					else
					{
						mario->Run(true);
					}
				}else if(ic.get_keyboard().get_keycode(CL_KEY_SPACE)&&!ic.get_keyboard().get_keycode(CL_KEY_LEFT)&&!ic.get_keyboard().get_keycode(CL_KEY_RIGHT)){
					mario->Jump(onPlace);
				}else if(ic.get_keyboard().get_keycode(CL_KEY_UP)){
					mario->Climb(up);
				}else if(ic.get_keyboard().get_keycode(CL_KEY_DOWN)){
					mario->Climb(down);
				}else{
					if(mario->IsJumping())
					{
						mario->Jump();
					}
					else
					{
						mario->Stand();
					}
				}
				princess->standingontop();
				donkeykong->fixedstanding();
				mario->hud(lifes);
				oilbarrel->processflame();
				oilbarrel->processoilbarrel();
				break;
			case win:
				donkeykong->loosingdonkey();
				princess->winning();
				mario->Stand();
				mario->hud(lifes);
				oilbarrel->processoilbarrel();
				if(donkeykong->getPosition().y > 700)
				{
					mario->setPosition(130, 605);
					donkeykong->reset(true);
					oilbarrel->reset();
					lifes = 3;
					gamestate = play;
					collision->setmario(mario->getPosition());
				}
				
				break;
			case loos:
				donkeykong->fixedstanding();
				princess->loosing();
				mario->dead();
				mario->hud(lifes);
				oilbarrel->processoilbarrel();
				if(ic.get_keyboard().get_keycode(CL_KEY_ENTER))
				{
					mario->setPosition(130, 605);
					collision->setmario(mario->getPosition());
					if(lifes > 0)
					{
						donkeykong->reset(false);
						oilbarrel->reset();
						gamestate = play;
					}
					else
					{
						lifes = 3;
						donkeykong->reset(true);
						oilbarrel->reset();
						gamestate = gameover;
					}
				}
				break;
			case gameover:
				g->getGrafikMap()->draw(gc, 0, 0);
				if(ic.get_keyboard().get_keycode(CL_KEY_SPACE))
				{
					gamestate = play;
				}
				break;
			default:
				break;
			}
			window.flip();
			CL_KeepAlive::process();

			current_time = CL_System::get_time();
			time_to_sleep_for = main_loop_rate - (current_time - last_time);
			if (time_to_sleep_for > 0)
				CL_System::sleep(time_to_sleep_for);


		}
		delete w;
		delete mario;
		delete donkeykong;
		delete princess;
		delete wsound;
		return 0;
	}
};

CL_ClanApplication app(&ConsoleProgram::main);